#include <stdio.h>
#include <stdlib.h>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>

// Type Declarations

enum PrintBehavior {
    CloseAtSameLine,
    CloseAtOtherLine
};

/* Constant Declarations */
char Look;                    // Lookahead Character
const int buf_len = 64;
int DLevel = 0; // Debug log level

/* Print Token. Usage: PrintEnter(Token, CloseAtOtherLine/CloseAtSameLine).
   If CloseAtOtherLine, when going out of the Token name scope, you must call PrintLeave().
 */
void PrintEnter(const char* s, PrintBehavior behavior = CloseAtOtherLine) {
    for (int i = 0; i < DLevel; ++i) {
        printf("\t");
    }
    printf("<%s", s);
    if (behavior == CloseAtSameLine) {
        printf(">\n");
    }
    else {
        printf("\n");
        ++DLevel;
    }
}

void PrintLeave() {
    for (int i = 1; i < DLevel; ++i) {
        printf("\t", DLevel);
    }
    printf(">\n");
    --DLevel;
}

/* Read New Character From Input Stream */
void GetChar() {
  Look = getchar();
}

/* Report an Error */
template<typename T>
void WriteLn(const T& t) {
    std::cout << t << std::endl;
}

void Error(const std::string& s) {
  std::cout << std::endl;
  std::cout << "Error: " << s << "." << std::endl;
}

/* Report Error and Halt */
void Abort(const std::string& s) {
    Error(s);
    exit(0);
}

/* Report What Was Expected */
void Expected(const std::string& s) {
    Abort(s + " Expected");
}

/* Recognize White Space */
int IsWhite(char c) {
    if (c==' ' ||
        c=='\t') {
        return 1;
    }
    else {
        return 0;
    }
    // return isspace(c);
}

/* Skip Over Leading White Space */
void SkipWhite() {
  while (IsWhite(Look)) {
	GetChar();
  }
}

// Skip Over a Comma
void SkipComma() {
    SkipWhite();
    if (Look == ',') {
        GetChar();
        SkipWhite();
    }
}


// Skip a CRLF
void Fin() {
    while ((Look == '\n') || (Look == '\r')) {
        GetChar();
    }
    SkipWhite();
}

/* Match a Specific Input Character */
void Match(char x) {
  if (Look == x) {
	GetChar();
  }
  else {
	char buf[buf_len] = {0};
	sprintf(buf, "'''' %c ''''", x);
	Expected(buf);
  }
}

/* Recognize an Alpha Character  */
int IsAlpha(char c) {
  return isalpha(c);
}

/* Recognize a Decimal Digit */
int IsDigit(char c) {
  return isdigit(c);
}

/* Recognize an Addop */
int IsAddop(char c) {
  if ((c == '+') ||
	  (c == '-')) {
	return 1;
  }
  else {
	return 0;
  }
}

/* Get an Identifier */
char GetName() {
  if (!IsAlpha(Look)) {
	Expected("Name");
  }

  char result = Look;
  GetChar();
  return result;
}

/* Get a Number */
char GetNum() {
  if (!IsDigit(Look)) {
	Expected("Integer");
  }

  char result = Look;
  GetChar();
  return result;
}

/* Output a String with Tab */
void EmitLn(const std::string& s) {
  std::cout << "\t " << s << std::endl;
}

/* Initialize */
void Init() {
  GetChar();
}

/* Main Program */
int main(int argc, char** argv) {
  Init();

  return 0;
}
